
#include <string>

#include "ConfigFile.h"

#include <fstream>
#include <sstream>

ConfigFile *ConfigFile::parseConfig(const char *filePath) throw (string) {
    ifstream ifs(filePath);
    if (!ifs) {
        stringstream ss;
        ss << "ERROR: can not find config file \"" << filePath << "\"";

        throw ss.str();
    }

    string temp, key, value;
    string::size_type offset1, offset2, offset3;
    int line = 0;
    ConfigFile *config = new ConfigFile;

    while (!ifs.eof()) {
        getline(ifs, temp);

        ++line; // begin with 1

        if (temp.size() == 0) {
            continue;
        }
        if (temp[temp.length() - 1] == '\r') { //windows format
            temp[temp.length() - 1] = ' ';
        }

        offset1 = temp.find_first_not_of(" ");
        if (offset1 == string::npos || temp[offset1] == '#') {
            continue;
        }

        offset2 = temp.find_first_of("=");
        if (offset1 == offset2) {
            stringstream ss;
            ss << "ERROR: at line " << line << ": key should not be null";

            throw ss.str();
        }

        if (offset2 == string::npos || temp.find_first_of("=", offset2 + 1) != string::npos) {
            stringstream ss;
            ss << "ERROR: at line " << line << ": invalid format";

            throw ss.str();
        }

        for (offset3 = offset2 - 1; offset3 >= offset1 && temp[offset3] == ' '; offset3--) {
        }
        //offset3 = temp.find_last_not_of(" ", offset1, offset2 - offset1); // something wrong with unicode
        key.assign(temp, offset1, offset3 - offset1 + 1);

        offset1 = temp.find_first_not_of(" ", offset2 + 1);
        if (offset1 == string::npos) {
            stringstream ss;
            ss << "ERROR: at line " << line << ": value should not be null";

            throw ss.str();
        }

        for (offset2 = temp.size() - 1; offset2 >= 0 && temp[offset2] == ' '; offset2--) {
        }
        //offset2 = temp.find_last_not_of(" "); // something wrong with unicode
        value.assign(temp, offset1, offset2 - offset1 + 1);

        if (config->put(key, value) == false) {
            stringstream ss;
            ss << "ERROR: at line " << line << ": duplicated key \"" << key << "\"";

            throw ss.str();
        }
    }

    return config;
}

bool ConfigFile::put(string key, string value) {
    pair < map<string, string>::iterator, bool> res;

    res = m_config.insert(pair<string, string > (key, value));

    return res.second;
}

void ConfigFile::store(const char *filePath) {
    ofstream ofs(filePath);

    for (map<string, string>::iterator itr = m_config.begin(); itr != m_config.end(); itr++) {
        ofs << itr->first << "=" << itr->second << endl;
    }
}
